// *****************************************************************************
// *****************************************************************************
// Copyright 2013 - 2016, Cadence Design Systems
//
// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source
// Distribution,  Product Version 5.8.
//
// Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
//    implied. See the License for the specific language governing
//    permissions and limitations under the License.
//
// For updates, support, or to become part of the LEF/DEF Community,
// check www.openeda.org for details.
//
//  $Author: dell $
//  $Revision: #1 $
//  $Date: 2020/09/29 $
//  $State:  $
// *****************************************************************************
// *****************************************************************************

#include "defiComponent.hpp"

#include <cstdlib>
#include <cstring>

#include "defiDebug.hpp"
#include "defiUtil.hpp"
#include "defrData.hpp"

BEGIN_DEF_PARSER_NAMESPACE

/*********************************************************
 * class defiComponentMaskShiftLayer
 **********************************************************/
defiComponentMaskShiftLayer::defiComponentMaskShiftLayer(defrData* data)
    : defData(data)
{
  Init();
}

defiComponentMaskShiftLayer::~defiComponentMaskShiftLayer()
{
  Destroy();
}

void defiComponentMaskShiftLayer::Init()
{
  layersAllocated_ = 0;
  numLayers_ = 0;
  layers_ = nullptr;

  bumpLayers(16);
}

void defiComponentMaskShiftLayer::Destroy()
{
  if (numLayers_) {
    for (int i = 0; i < numLayers_; i++) {
      if (layers_[i]) {
        free(layers_[i]);
      }
    }
    free((char*) (layers_));
  } else {
    if (layersAllocated_) {
      free((char*) (layers_));
    }
  }
  layersAllocated_ = 0;
  numLayers_ = 0;
  layers_ = nullptr;
}

void defiComponentMaskShiftLayer::addMaskShiftLayer(const char* layer)
{
  int len = strlen(layer) + 1;
  if (numLayers_ == layersAllocated_) {
    bumpLayers(numLayers_ * 2);
  }
  layers_[numLayers_] = (char*) malloc(len);
  strcpy(layers_[numLayers_], defData->DEFCASE(layer));
  (numLayers_)++;
}

void defiComponentMaskShiftLayer::bumpLayers(int size)
{
  int i;
  char** newLayers = (char**) malloc(sizeof(char*) * size);
  for (i = 0; i < numLayers_; i++) {
    newLayers[i] = layers_[i];
  }
  if (layers_) {
    free((char*) (layers_));
  }
  layers_ = newLayers;
  layersAllocated_ = size;
}

void defiComponentMaskShiftLayer::clear()
{
  for (int i = 0; i < numLayers_; i++) {
    free(layers_[i]);
  }
  numLayers_ = 0;
}

int defiComponentMaskShiftLayer::numMaskShiftLayers() const
{
  return numLayers_;
}

const char* defiComponentMaskShiftLayer::maskShiftLayer(int index) const
{
  if (index >= 0 && index < numLayers_) {
    return layers_[index];
  }

  return nullptr;
}

/*********************************************************
 * class defiComponent
 **********************************************************/
defiComponent::defiComponent(defrData* data) : defData(data)
{
  Init();
}

void defiComponent::Init()
{
  id_ = nullptr;
  name_ = nullptr;
  regionName_ = nullptr;
  foreignName_ = nullptr;
  Fori_ = 0;
  EEQ_ = nullptr;
  generateName_ = nullptr;
  macroName_ = nullptr;
  generateNameSize_ = 0;
  maskShiftSize_ = 0;
  maskShift_ = nullptr;
  macroNameSize_ = 0;
  minLayerSize_ = 0;
  maxLayerSize_ = 0;
  minLayer_ = nullptr;
  maxLayer_ = nullptr;
  nets_ = nullptr;
  source_ = nullptr;
  numNets_ = 0;
  bumpName(16);
  bumpId(16);
  bumpRegionName(16);
  bumpEEQ(16);
  bumpNets(16);
  bumpForeignName(16);
  bumpMinLayer(16);
  bumpMaxLayer(16);
  numProps_ = 0;
  propsAllocated_ = 2;
  names_ = (char**) malloc(sizeof(char*) * 2);
  values_ = (char**) malloc(sizeof(char*) * 2);
  dvalues_ = (double*) malloc(sizeof(double) * 2);
  types_ = (char*) malloc(sizeof(char) * 2);
  clear();

  numRects_ = 0;
  rectsAllocated_ = 1;
  rectXl_ = (int*) malloc(sizeof(int) * 1);
  rectYl_ = (int*) malloc(sizeof(int) * 1);
  rectXh_ = (int*) malloc(sizeof(int) * 1);
  rectYh_ = (int*) malloc(sizeof(int) * 1);
}

void defiComponent::Destroy()
{
  free(name_);
  free(regionName_);
  free(id_);
  free(EEQ_);
  free(minLayer_);
  free(maxLayer_);
  free((char*) (nets_));
  netsAllocated_ = 0;  // avoid freeing again later
  if (source_) {
    free(source_);
  }
  if (foreignName_) {
    free(foreignName_);
  }
  if (generateName_) {
    free(generateName_);
  }
  if (macroName_) {
    free(macroName_);
  }
  if (netsAllocated_) {
    free((char*) (nets_));
  }
  free((char*) (maskShift_));
  free((char*) (names_));
  free((char*) (values_));
  free((char*) (dvalues_));
  free((char*) (types_));
  free((char*) (rectXl_));
  free((char*) (rectYl_));
  free((char*) (rectXh_));
  free((char*) (rectYh_));
}

defiComponent::~defiComponent()
{
  Destroy();
}

void defiComponent::IdAndName(const char* id, const char* name)
{
  int len;

  clear();

  if ((len = strlen(id) + 1) > idSize_) {
    bumpId(len);
  }
  strcpy(id_, defData->DEFCASE(id));

  if ((len = strlen(name) + 1) > nameSize_) {
    bumpName(len);
  }
  strcpy(name_, defData->DEFCASE(name));
}

const char* defiComponent::source() const
{
  return source_;
}

int defiComponent::weight() const
{
  return weight_;
}

void defiComponent::setWeight(int w)
{
  weight_ = w;
  hasWeight_ = 1;
}

int defiComponent::maskShift(int index) const
{
  if (index < 0 || index >= maskShiftSize_) {
    defiError(1, 0, "bad index for component maskShift", defData);
    return 0;
  }

  return maskShift_[index];
}

void defiComponent::setMaskShift(const char* shiftMask)
{
  int shiftMaskLength = strlen(shiftMask);

  maskShift_ = (int*) malloc(sizeof(int) * shiftMaskLength);
  maskShiftSize_ = shiftMaskLength;

  for (int i = 0; i < shiftMaskLength; i++) {
    int curShift = shiftMask[i] - '0';

    // Strip possible error data.
    if (curShift > 9 || curShift < 0) {
      curShift = 0;
    }

    maskShift_[shiftMaskLength - i - 1] = curShift;
  }
}

void defiComponent::setGenerate(const char* newName, const char* macroName)
{
  int len = strlen(newName) + 1;

  if (generateNameSize_ < len) {
    if (generateName_) {
      free(generateName_);
    }
    generateName_ = (char*) malloc(len);
    generateNameSize_ = len;
  }
  strcpy(generateName_, defData->DEFCASE(newName));

  len = strlen(macroName) + 1;
  if (macroNameSize_ < len) {
    if (macroName_) {
      free(macroName_);
    }
    macroName_ = (char*) malloc(len);
    macroNameSize_ = len;
  }
  strcpy(macroName_, defData->DEFCASE(macroName));

  hasGenerate_ = 1;  // Ying Tan fix at 20010918
}

void defiComponent::setSource(const char* name)
{
  int len = strlen(name) + 1;
  source_ = (char*) malloc(len);
  strcpy(source_, defData->DEFCASE(name));
}

void defiComponent::setRegionName(const char* name)
{
  int len;

  if ((len = strlen(name) + 1) > regionNameSize_) {
    bumpRegionName(len);
  }
  strcpy(regionName_, defData->DEFCASE(name));
  hasRegionName_ = 1;
}

void defiComponent::setEEQ(const char* name)
{
  int len;

  if ((len = strlen(name) + 1) > EEQSize_) {
    bumpEEQ(len);
  }
  strcpy(EEQ_, defData->DEFCASE(name));
  hasEEQ_ = 1;
}

void defiComponent::setPlacementStatus(int n)
{
  status_ = n;
}

void defiComponent::setPlacementLocation(int x, int y, int orient)
{
  x_ = x;
  y_ = y;
  orient_ = orient;
}

void defiComponent::setRegionBounds(int xl, int yl, int xh, int yh)
{
  int i;
  i = numRects_;
  if (i == rectsAllocated_) {
    int max = rectsAllocated_ * 2;
    int* nxl = (int*) malloc(sizeof(int) * max);
    int* nyl = (int*) malloc(sizeof(int) * max);
    int* nxh = (int*) malloc(sizeof(int) * max);
    int* nyh = (int*) malloc(sizeof(int) * max);
    for (i = 0; i < numRects_; i++) {
      nxl[i] = rectXl_[i];
      nyl[i] = rectYl_[i];
      nxh[i] = rectXh_[i];
      nyh[i] = rectYh_[i];
    }
    free((char*) (rectXl_));
    free((char*) (rectYl_));
    free((char*) (rectXh_));
    free((char*) (rectYh_));
    rectXl_ = nxl;
    rectYl_ = nyl;
    rectXh_ = nxh;
    rectYh_ = nyh;
    rectsAllocated_ = max;
  }
  rectXl_[i] = xl;
  rectYl_[i] = yl;
  rectXh_[i] = xh;
  rectYh_[i] = yh;
  numRects_ += 1;
}

// 5.6
void defiComponent::setHalo(int left, int bottom, int right, int top)
{
  hasHalo_ = 1;
  leftHalo_ = left;
  bottomHalo_ = bottom;
  rightHalo_ = right;
  topHalo_ = top;
}

// 5.7
void defiComponent::setHaloSoft()
{
  hasHaloSoft_ = 1;
}

// 5.7
void defiComponent::setRouteHalo(int haloDist,
                                 const char* minLayer,
                                 const char* maxLayer)
{
  int len;

  haloDist_ = haloDist;
  if ((len = strlen(minLayer) + 1) > minLayerSize_) {
    bumpMinLayer(len);
  }
  strcpy(minLayer_, defData->DEFCASE(minLayer));
  if ((len = strlen(maxLayer) + 1) > maxLayerSize_) {
    bumpMaxLayer(len);
  }
  strcpy(maxLayer_, defData->DEFCASE(maxLayer));
}

void defiComponent::changeIdAndName(const char* id, const char* name)
{
  int len;

  if ((len = strlen(id) + 1) > idSize_) {
    bumpId(len);
  }
  strcpy(id_, defData->DEFCASE(id));

  if ((len = strlen(name) + 1) > nameSize_) {
    bumpName(len);
  }
  strcpy(name_, defData->DEFCASE(name));
}

const char* defiComponent::id() const
{
  return id_;
}

const char* defiComponent::name() const
{
  return name_;
}

int defiComponent::placementStatus() const
{
  return status_;
}

int defiComponent::placementX() const
{
  return x_;
}

int defiComponent::placementY() const
{
  return y_;
}

int defiComponent::placementOrient() const
{
  return orient_;
}

const char* defiComponent::placementOrientStr() const
{
  return (defiOrientStr(orient_));
}

const char* defiComponent::regionName() const
{
  return regionName_;
}

const char* defiComponent::EEQ() const
{
  return EEQ_;
}

const char* defiComponent::generateName() const
{
  return generateName_;
}

const char* defiComponent::macroName() const
{
  return macroName_;
}

void defiComponent::regionBounds(int* size,
                                 int** xl,
                                 int** yl,
                                 int** xh,
                                 int** yh) const
{
  *size = numRects_;
  *xl = rectXl_;
  *yl = rectYl_;
  *xh = rectXh_;
  *yh = rectYh_;
}

void defiComponent::bumpId(int size)
{
  if (id_) {
    free(id_);
  }
  id_ = (char*) malloc(size);
  idSize_ = size;
  *(id_) = '\0';
}

void defiComponent::bumpName(int size)
{
  if (name_) {
    free(name_);
  }
  name_ = (char*) malloc(size);
  nameSize_ = size;
  *(name_) = '\0';
}

void defiComponent::bumpRegionName(int size)
{
  if (regionName_) {
    free(regionName_);
  }
  regionName_ = (char*) malloc(size);
  regionNameSize_ = size;
  *(regionName_) = '\0';
}

void defiComponent::bumpEEQ(int size)
{
  if (EEQ_) {
    free(EEQ_);
  }
  EEQ_ = (char*) malloc(size);
  EEQSize_ = size;
  *(EEQ_) = '\0';
}

void defiComponent::bumpMinLayer(int size)
{
  if (minLayer_) {
    free(minLayer_);
  }
  minLayer_ = (char*) malloc(size);
  minLayerSize_ = size;
  *(minLayer_) = '\0';
}

void defiComponent::bumpMaxLayer(int size)
{
  if (maxLayer_) {
    free(maxLayer_);
  }
  maxLayer_ = (char*) malloc(size);
  maxLayerSize_ = size;
  *(maxLayer_) = '\0';
}

void defiComponent::clear()
{
  int i;

  if (id_) {
    *(id_) = '\0';
  }
  if (name_) {
    *(name_) = '\0';
  }
  if (regionName_) {
    *(regionName_) = '\0';
  }
  if (foreignName_) {
    *(foreignName_) = '\0';
  }
  if (EEQ_) {
    *(EEQ_) = '\0';
  }
  if (minLayer_) {
    *(minLayer_) = '\0';
  }
  if (maxLayer_) {
    *(maxLayer_) = '\0';
  }
  Fori_ = 0;
  status_ = 0;
  hasRegionName_ = 0;
  hasForeignName_ = 0;
  hasFori_ = 0;
  hasEEQ_ = 0;
  hasWeight_ = 0;
  hasGenerate_ = 0;
  if (maskShiftSize_) {
    free((int*) (maskShift_));
  }
  maskShift_ = nullptr;
  maskShiftSize_ = 0;
  weight_ = 0;
  if (source_) {
    free(source_);
  }
  for (i = 0; i < numNets_; i++) {
    free(nets_[i]);
  }
  numNets_ = 0;
  source_ = nullptr;
  hasHalo_ = 0;
  hasHaloSoft_ = 0;
  haloDist_ = 0;
  leftHalo_ = 0;
  bottomHalo_ = 0;
  rightHalo_ = 0;
  topHalo_ = 0;
  for (i = 0; i < numProps_; i++) {
    free(names_[i]);
    free(values_[i]);
    dvalues_[i] = 0;
  }
  numProps_ = 0;
  numRects_ = 0;
}

int defiComponent::isUnplaced() const
{
  return status_ == DEFI_COMPONENT_UNPLACED ? 1 : 0;
}

int defiComponent::isPlaced() const
{
  return status_ == DEFI_COMPONENT_PLACED ? 1 : 0;
}

int defiComponent::isFixed() const
{
  return status_ == DEFI_COMPONENT_FIXED ? 1 : 0;
}

int defiComponent::isCover() const
{
  return status_ == DEFI_COMPONENT_COVER ? 1 : 0;
}

void defiComponent::print(FILE* fout) const
{
  fprintf(fout, "Component id '%s' name '%s'", id(), name());
  if (isPlaced()) {
    fprintf(fout,
            " Placed at %d,%d orient %s",
            placementX(),
            placementY(),
            placementOrientStr());
  }
  if (isFixed()) {
    fprintf(fout,
            " Fixed at %d,%d orient %s",
            placementX(),
            placementY(),
            placementOrientStr());
  }
  if (isCover()) {
    fprintf(fout,
            " Cover at %d,%d orient %s",
            placementX(),
            placementY(),
            placementOrientStr());
  }
  fprintf(fout, "\n");

  if (hasGenerate()) {
    fprintf(fout, "  generate %s %s\n", generateName(), macroName());
  }
  if (hasWeight()) {
    fprintf(fout, "  weight %d\n", weight());
  }
  if (maskShiftSize()) {
    fprintf(fout, "  maskShift ");

    for (int i = 0; i < maskShiftSize(); i++) {
      fprintf(fout, " %d", maskShift(i));
    }
    fprintf(fout, "\n");
  }
  if (hasSource()) {
    fprintf(fout, "  source '%s'\n", source());
  }
  if (hasEEQ()) {
    fprintf(fout, "  EEQ '%s'\n", EEQ());
  }

  if (hasRegionName()) {
    fprintf(fout, "  Region '%s'\n", regionName());
  }
  if (hasRegionBounds()) {
    int size;
    int *xl, *yl, *xh, *yh;
    int j;
    regionBounds(&size, &xl, &yl, &xh, &yh);
    for (j = 0; j < size; j++) {
      fprintf(
          fout, "  Region bounds %d,%d %d,%d\n", xl[j], yl[j], xh[j], yh[j]);
    }
  }
  if (hasNets()) {
    int i;
    fprintf(fout, " Net connections:\n");
    for (i = 0; i < numNets(); i++) {
      fprintf(fout, "  '%s'\n", net(i));
    }
  }
}

int defiComponent::hasRegionName() const
{
  return (int) (hasRegionName_);
}

int defiComponent::hasGenerate() const
{
  return (int) (hasGenerate_);
}

int defiComponent::hasWeight() const
{
  return (int) (hasWeight_);
}

int defiComponent::maskShiftSize() const
{
  return maskShiftSize_;
}

int defiComponent::hasSource() const
{
  return source_ ? 1 : 0;
}

int defiComponent::hasRegionBounds() const
{
  return numRects_ ? 1 : 0;
}

int defiComponent::hasEEQ() const
{
  return (int) (hasEEQ_);
}

int defiComponent::hasNets() const
{
  return numNets_ ? 1 : 0;
}

int defiComponent::numNets() const
{
  return numNets_;
}

// 5.6
int defiComponent::hasHalo() const
{
  return hasHalo_;
}

// 5.7
int defiComponent::hasHaloSoft() const
{
  return hasHaloSoft_;
}

// 5.7
int defiComponent::hasRouteHalo() const
{
  return haloDist_;
}

// 5.7
int defiComponent::haloDist() const
{
  return haloDist_;
}

// 5.7
const char* defiComponent::minLayer() const
{
  return minLayer_;
}

// 5.7
const char* defiComponent::maxLayer() const
{
  return maxLayer_;
}

void defiComponent::haloEdges(int* left, int* bottom, int* right, int* top)
{
  *left = leftHalo_;
  *bottom = bottomHalo_;
  *right = rightHalo_;
  *top = topHalo_;
}

void defiComponent::reverseNetOrder()
{
  // Reverse the order of the items in the nets array.
  int one = 0;
  int two = numNets_ - 1;
  char* t;
  while (one < two) {
    t = nets_[one];
    nets_[one] = nets_[two];
    nets_[two] = t;
    one++;
    two--;
  }
}

char* defiComponent::propName(int index) const
{
  if (index < 0 || index >= numProps_) {
    defiError(1, 0, "bad index for component property", defData);
    return nullptr;
  }
  return names_[index];
}

char* defiComponent::propValue(int index) const
{
  if (index < 0 || index >= numProps_) {
    defiError(1, 0, "bad index for component property", defData);
    return nullptr;
  }
  return values_[index];
}

double defiComponent::propNumber(int index) const
{
  if (index < 0 || index >= numProps_) {
    defiError(1, 0, "bad index for component property", defData);
    return 0;
  }
  return dvalues_[index];
}

char defiComponent::propType(int index) const
{
  if (index < 0 || index >= numProps_) {
    defiError(1, 0, "bad index for component property", defData);
    return 0;
  }
  return types_[index];
}

int defiComponent::propIsNumber(int index) const
{
  if (index < 0 || index >= numProps_) {
    defiError(1, 0, "bad index for component property", defData);
    return 0;
  }
  return dvalues_[index] ? 1 : 0;
}

int defiComponent::propIsString(int index) const
{
  if (index < 0 || index >= numProps_) {
    defiError(1, 0, "bad index for component property", defData);
    return 0;
  }
  return dvalues_[index] ? 0 : 1;
}

int defiComponent::numProps() const
{
  return numProps_;
}

void defiComponent::addProperty(const char* name,
                                const char* value,
                                const char type)
{
  int len = strlen(name) + 1;
  if (numProps_ == propsAllocated_) {
    int i;
    char** nn;
    char** nv;
    double* nd;
    char* nt;

    propsAllocated_ *= 2;
    nn = (char**) malloc(sizeof(char*) * propsAllocated_);
    nv = (char**) malloc(sizeof(char*) * propsAllocated_);
    nd = (double*) malloc(sizeof(double) * propsAllocated_);
    nt = (char*) malloc(sizeof(char) * propsAllocated_);
    for (i = 0; i < numProps_; i++) {
      nn[i] = names_[i];
      nv[i] = values_[i];
      nd[i] = dvalues_[i];
      nt[i] = types_[i];
    }
    free((char*) (names_));
    free((char*) (values_));
    free((char*) (dvalues_));
    free((char*) (types_));
    names_ = nn;
    values_ = nv;
    dvalues_ = nd;
    types_ = nt;
  }
  names_[numProps_] = (char*) malloc(len);
  strcpy(names_[numProps_], defData->DEFCASE(name));
  len = strlen(value) + 1;
  values_[numProps_] = (char*) malloc(len);
  strcpy(values_[numProps_], defData->DEFCASE(value));
  dvalues_[numProps_] = 0;
  types_[numProps_] = type;
  numProps_ += 1;
}

void defiComponent::addNumProperty(const char* name,
                                   const double d,
                                   const char* value,
                                   const char type)
{
  int len = strlen(name) + 1;
  if (numProps_ == propsAllocated_) {
    int i;
    char** nn;
    char** nv;
    double* nd;
    char* nt;

    propsAllocated_ *= 2;
    nn = (char**) malloc(sizeof(char*) * propsAllocated_);
    nv = (char**) malloc(sizeof(char*) * propsAllocated_);
    nd = (double*) malloc(sizeof(double) * propsAllocated_);
    nt = (char*) malloc(sizeof(char) * propsAllocated_);
    for (i = 0; i < numProps_; i++) {
      nn[i] = names_[i];
      nv[i] = values_[i];
      nd[i] = dvalues_[i];
      nt[i] = types_[i];
    }
    free((char*) (names_));
    free((char*) (values_));
    free((char*) (dvalues_));
    free((char*) (types_));
    names_ = nn;
    values_ = nv;
    dvalues_ = nd;
    types_ = nt;
  }
  names_[numProps_] = (char*) malloc(len);
  strcpy(names_[numProps_], defData->DEFCASE(name));
  len = strlen(value) + 1;
  values_[numProps_] = (char*) malloc(len);
  strcpy(values_[numProps_], defData->DEFCASE(value));
  dvalues_[numProps_] = d;
  types_[numProps_] = type;
  numProps_ += 1;
}

void defiComponent::addNet(const char* net)
{
  int len = strlen(net) + 1;
  if (numNets_ == netsAllocated_) {
    bumpNets(numNets_ * 2);
  }
  nets_[numNets_] = (char*) malloc(len);
  strcpy(nets_[numNets_], defData->DEFCASE(net));
  (numNets_)++;
}

void defiComponent::bumpNets(int size)
{
  int i;
  char** newNets = (char**) malloc(sizeof(char*) * size);
  for (i = 0; i < numNets_; i++) {
    newNets[i] = nets_[i];
  }
  free((char*) (nets_));
  nets_ = newNets;
  netsAllocated_ = size;
}

const char* defiComponent::net(int index) const
{
  if (index >= 0 && index < numNets_) {
    return nets_[index];
  }
  return nullptr;
}

void defiComponent::bumpForeignName(int size)
{
  if (foreignName_) {
    free(foreignName_);
  }
  foreignName_ = (char*) malloc(sizeof(char) * size);
  foreignNameSize_ = size;
  *(foreignName_) = '\0';
}

void defiComponent::setForeignName(const char* name)
{
  int len;

  if (hasForeignName()) {
    defiError(1,
              0,
              "Multiple define of '+ FOREIGN' in COMPONENT is not supported.\n",
              defData);
  }
  if ((len = strlen(name) + 1) > foreignNameSize_) {
    bumpForeignName(len);
  }
  strcpy(foreignName_, defData->DEFCASE(name));
  hasForeignName_ = 1;
}

void defiComponent::setForeignLocation(int x, int y, int orient)
{
  Fx_ = x;
  Fy_ = y;
  Fori_ = orient;
  hasFori_ = 1;
}

int defiComponent::hasForeignName() const
{
  return (int) (hasForeignName_);
}

const char* defiComponent::foreignName() const
{
  return foreignName_;
}

int defiComponent::foreignX() const
{
  return Fx_;
}

int defiComponent::foreignY() const
{
  return Fy_;
}

int defiComponent::hasFori() const
{
  return (int) (hasFori_);
}

const char* defiComponent::foreignOri() const
{
  switch (Fori_) {
    case 0:
      return ("N");
    case 1:
      return ("W");
    case 2:
      return ("S");
    case 3:
      return ("E");
    case 4:
      return ("FN");
    case 5:
      return ("FW");
    case 6:
      return ("FS");
    case 7:
      return ("FE");
  }
  return nullptr;
}

int defiComponent::foreignOrient() const
{
  return Fori_;
}
END_DEF_PARSER_NAMESPACE
